/**
**************************************************************************************
*Palisma - Secrets of the Illuminati is an open-source 2D RPG                        *
*Copyright (C) 2006, Tony Sparks                                                     *
*                                                                                    *
*This library is free software; you can redistribute it and/or                       *
*modify it under the terms of the GNU Lesser General Public                          *
*License as published by the Free Software Foundation; either                        *
*version 2.1 of the License, or (at your option) any later version.                  *
*                                                                                    *
*This library is distributed in the hope that it will be useful,                     *
*but WITHOUT ANY WARRANTY; without even the implied warranty of                      *
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                   *
*Lesser General Public License for more details.                                     *
*                                                                                    *
*You should have received a copy of the GNU Lesser General Public                    *
*License along with this library; if not, write to the Free Software                 *
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA      *
**************************************************************************************
*/
#pragma once
#include <algorithm> 
#include <math.h>
#include <iostream>
#include "vector.h"
#pragma warning( disable : 4244)


/** Check to see if a line intersects another */
bool inline LineIntersectLine( Vector2f v1, Vector2f v2, Vector2f v3, Vector2f v4 )
{
    float denom = ((v4.y - v3.y) * (v2.x - v1.x)) - ((v4.x - v3.x) * (v2.y - v1.y));
    float numerator = ((v4.x - v3.x) * (v1.y - v3.y)) - ((v4.y - v3.y) * (v1.x - v3.x));

    float numerator2 = ((v2.x - v1.x) * (v1.y - v3.y)) - ((v2.y - v1.y) * (v1.x - v3.x));

    if ( denom == 0.0f ) return false;
    //{
    //    if ( numerator == 0.0f && numerator2 == 0.0f )
    //    {
    //        return false;//COINCIDENT;
    //    }
    //    return false;// PARALLEL;
    //}
    float ua = numerator / denom;
    float ub = numerator2/ denom;

    return (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f);
    //{
    //    Vector2f inter;
    //    // Get the intersection point.
    //    inter.x = v1.x + ua*(v2.x - v1.x);
    //    inter.y = v1.y + ua*(v2.y - v1.y);
    //    std::cout << "Interscetion: " << inter.x << " , " << inter.y << "\n";
    //    return true;//INTERESECTING;
    //}
    //return false;
    ////return NOT_INTERESECTING;
}

struct Rect
{

    int x;
    int y;
    int width;
    int height;
    
    // intersects another rect
    inline bool Intersects( const Rect &r ) {
        // check the map boundaries
        if ((r.x + r.width  < x)	|| 
		    (r.y + r.height < y)	||
            (r.x > x + width) || 
            (r.y > y + height) )
		    return false;

	    return true;
    };
    // intersects a point
    inline bool Intersects( int _x, int _y ) {
            return !( _x > x + width  ||
                      _y > y + height ||
                      _x < x ||
                      _y < y );
    };
    // intersects a line
    bool LineIntersects( const Vector2f &v1, const Vector2f &v2 )
    {
        Vector2f lowerLeft( x, y+height );
        Vector2f upperRight( x+width, y );
        Vector2f upperLeft( x, y );
        Vector2f lowerRight( x+width, y+height);
        // check if it is inside
        if (v1.x > lowerLeft.x && v1.x < upperRight.x && v1.y < lowerLeft.y && v1.y > upperRight.y &&
            v2.x > lowerLeft.x && v2.x < upperRight.x && v2.y < lowerLeft.y && v2.y > upperRight.y )
        {   
            return true;
        }
        // check each line for intersection
        if (LineIntersectLine(v1,v2, upperLeft, lowerLeft ) ) return true;
        if (LineIntersectLine(v1,v2, lowerLeft, lowerRight) ) return true;
        if (LineIntersectLine(v1,v2, upperLeft, upperRight) ) return true;
        if (LineIntersectLine(v1,v2, upperRight, lowerRight) ) return true;
        return false;
    }


    void Reset() { x = y = width = height = 0; };
    void Set(int _x, int _y, int w, int h )
    {
        x = _x; y = _y;
        width = w;
        height = h;
    };

    Rect() { Reset(); };
    Rect( int _x, int _y, int w, int h ) : x(_x), y(_y), width(w), height(h) {};
    virtual ~Rect() {};
};


class MPoint {
public:
    MPoint() { x=0;y=0;};
    MPoint(int _x, int _y ) { x = _x; y = _y; };
    int x;
    int y;
    ~MPoint() {};
};


/**
=============================
Geometry Object
Anything that needs collision
or culling
=============================
*/
class GeometryObject
{
    // TODO
};